﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using NetSurveillance.WebApp.DataServices.Models;
using NetSurveillance.WebApp.Models;
using NetSurveillance.WebApp.Utilities;
using Newtonsoft.Json;
using ServiceStack.Text;

namespace NetSurveillance.WebApp.Controllers
{
    public class TaskController : BaseController
    {
        public ActionResult HostScan()
        {
            long? interActiveId = ApplicationContainer.Read<long?>(PresetValues.InteractiveKeys.HostScanning);
            var currentTimespan =
                    DateTime.Now - ApplicationContainer.Read<DateTime>(PresetValues.ApplicationKeys.HostScanTime);
            if (interActiveId.HasValue && currentTimespan.TotalSeconds < PresetValues.Timeouts.HostScan)
                ViewBag.IsLocking = true;
            else
            {
                RemoveHostScanCache();
            }
            return View();
        }

        [HttpPost]
        public ActionResult PerformsAScan(HostScanModel hostScanModel)
        {
            if (!ModelState.IsValid)
                return
                    Json(new AjaxResult(false,
                                        string.Join(@"\r\n", ModelState.Values.Select(
                                            p =>
                                            p.Errors.Any()
                                                ? string.Join(",", p.Errors.Select(e => e.ErrorMessage))
                                                : string.Empty))));

            var interActive = new Interactive { InteractiveType = "scanip", InteractiveStatus = InteractiveStatus.Starting };
            var serverResult = DataProvider.InteractiveService.Save(interActive);
            if (serverResult.ExecutedSuccess)
            {
                var axu = ActionXmlUtility.Instance;
                var actionEle = axu.CreateHostScanXml(interActive.Id, hostScanModel.StartIP, hostScanModel.EndIP);
                if (Connector.SendAction(actionEle, PresetValues.MonitorIp, PresetValues.MonitorPort))
                {
                    ApplicationContainer.Add(PresetValues.ApplicationKeys.HostScanTime, DateTime.Now);
                    ApplicationContainer.Add(PresetValues.InteractiveKeys.HostScanning, interActive.Id);
                    return Json(AjaxResult.TrueResult);
                }
                return Json(new AjaxResult(false, "启动扫描失败！"));
            }
            return Json(new AjaxResult(false, "添加命令失败！"));
        }

        [HttpPost]
        public ActionResult ExcuteHostScan(string maxHostResultId)
        {
            var resultOfSendAction = new AjaxResult(false, "未开始扫描!") { Expandos = new { neverStart = true } };
            long interactiveId = ApplicationContainer.Read<long>(PresetValues.InteractiveKeys.HostScanning);
            //当前扫描的状态实体
            var currentStatusModel = DataProvider.InteractiveService.GetModelById(interactiveId);
            if (interactiveId > 0 && currentStatusModel != null)
            {
                var currentTimespan =
                    DateTime.Now - ApplicationContainer.Read<DateTime>(PresetValues.ApplicationKeys.HostScanTime);
                //如果当前状态为starting 并且扫描时间大于默认时间则超时
                if (currentTimespan.TotalSeconds >= PresetValues.Timeouts.HostScan)
                {
                    SaveInteractiveTimeout(currentStatusModel);
                    RemoveHostScanCache();
                    resultOfSendAction = new AjaxResult(false, "扫描超时!") { Expandos = new { timeout = true } };
                    return Json(resultOfSendAction);
                }

                long maxHostScanId;
                //当第一次请求有数据或是默认的最大id为0 则第二次进入
                if (!string.IsNullOrWhiteSpace(maxHostResultId) &&
                    long.TryParse(maxHostResultId, out maxHostScanId))
                {
                    var listHostScanResults =
                        DataProvider.HostScanResultService.GetAllModels(false, p => p.Id > maxHostScanId).ToList();
                    string listModelsStr = null;
                    long? maxId = null;
                    if (listHostScanResults.Any())
                    {
                        maxHostScanId = listHostScanResults.Max(p => p.Id);
                        listModelsStr = JsonConvert.SerializeObject(listHostScanResults, Formatting.Indented);
                    }
                    string scanEnd;
                    if (currentStatusModel.InteractiveStatus == InteractiveStatus.Starting)
                    {
                        scanEnd = "no";
                        maxId = maxHostScanId;
                    }
                    else
                    {
                        scanEnd = "yes";
                        RemoveHostScanCache();
                    }
                    dynamic expandoProperties = new {scanEnd, listModels = listModelsStr, maxId};
                    resultOfSendAction = new AjaxResult(true) { Expandos = expandoProperties };
                }
                else
                { //第一次进入时默认为空 读取hostScanResult表中数据
                    var modelList = DataProvider.HostScanResultService.GetAllModels().ToList();
                    //如果存在 则返回数据和此时最大Id
                    if (modelList.Any())
                    {
                        maxHostScanId = modelList.Max(p => p.Id);
                        resultOfSendAction =
                            new AjaxResult(true)
                                {
                                    Expandos = new
                                        {
                                            maxId = maxHostScanId,
                                            listModels =
                                                JsonConvert.SerializeObject(modelList, Formatting.Indented),
                                            scanEnd = "no"
                                        }
                                };
                    }
                    else//此时如果没有数据则此时最大id为默认的maxHostScanId=0
                    {
                        resultOfSendAction =
                            new AjaxResult(true)
                                {
                                    Expandos = new { maxId = 0, scanEnd = "no" }
                                };
                    }
                }
            }
            return Json(resultOfSendAction);
        }

        private void RemoveHostScanCache()
        {
            ApplicationContainer.Remove(PresetValues.InteractiveKeys.HostScanning);
            ApplicationContainer.Remove(PresetValues.ApplicationKeys.HostScanTime);
        }

        [HttpPost]
        public ActionResult StopHostScan()
        {
            var axu = ActionXmlUtility.Instance;
            var actionEle = axu.CreateStopHostScanElement();
            bool sendSucc = Connector.SendAction(actionEle, PresetValues.MonitorIp, PresetValues.MonitorPort);
            if (sendSucc)
                RemoveHostScanCache();
            return CamelCaseJson(new AjaxResult(sendSucc, sendSucc ? null : "发送命令失败"));
        }

        public ActionResult TaskDetail()
        {
            if (CurrentTask == null)
            {
                TempData[PresetValues.TempDataKeys.ErrorMessage] = "没有正在运行的会话,无法查看当前会话";
                return RedirectToAction("Index", "Home");
            }
            ViewBag.TreeData = SerializeObject(GeneratorTreeData(CurrentTask.Id));
            return View();
        }

        public ActionResult ReGenerateTree()
        {
            return CurrentTask != null ? CamelCaseJson(GeneratorTreeData(CurrentTask.Id)) : null;
        }

        public ActionResult TaskHistory()
        {
            ViewBag.TreeData = SerializeObject(GeneratorHistoryTreeData());
            return View();
        }

        public ActionResult DataRecordList(DataRecordListModel drlModel)
        {
            if (CurrentTask == null)
            {
                TempData[PresetValues.TempDataKeys.ErrorMessage] = "没有正在运行的会话,无法查看当前会话";
                return RedirectToAction("Index", "Home");
            }
            LoadDataRecordListViewData();
            if (string.IsNullOrWhiteSpace(drlModel.OrderField))
                drlModel.OrderField = "Id";
            if (string.IsNullOrWhiteSpace(drlModel.Order))
                drlModel.Order = "desc";
            drlModel.TaskId = CurrentTask.Id;
            var drFilter = new DataRecordFilter {TaskId = drlModel.TaskId};
            drFilter.MergeFrom(drlModel);
            DataContainer.Add(PresetValues.SessionKeys.SearchFilter, drFilter);
            SetDataRecordList(drlModel);
            return View(drlModel);
        }


        /// <summary>
        /// 暂停、开始或结束任务
        /// </summary>
        /// <param name="taskStatus">需要设置的状态值</param>
        /// <returns>是否成功通知后台</returns>
        [HttpPost]
        public ActionResult SetTaskStatus(TaskStatusType? taskStatus)
        {
            if (!taskStatus.HasValue)
                return CamelCaseJson(new AjaxResult(false, "没有该状态值"));
            var interactiveId = ApplicationContainer.Read<long?>(PresetValues.InteractiveKeys.SetTaskStatus);
            var setTaskStatusTime =
                ApplicationContainer.Read<DateTime?>(PresetValues.ApplicationKeys.SetTaskStatusTime);
            //确保当前线程中只有一个设置任务状态的操作，并且设置超时后不会锁住
            if (interactiveId.HasValue && setTaskStatusTime.HasValue &&
                (DateTime.Now - setTaskStatusTime.Value).TotalSeconds <=
                PresetValues.Timeouts.SetTaskStatus)
            {
                return CamelCaseJson(new AjaxResult(false, "当前已有个线程正在设置当前会话状态"));
            }
                
            var interActive = new Interactive
            {
                InteractiveType = "SetTaskStatus",
                InteractiveStatus = InteractiveStatus.Starting
            };
            var serviceResult = DataProvider.InteractiveService.Save(interActive);
            if (serviceResult.ExecutedSuccess)
            {
                var rootElement = ActionXmlUtility.Instance.CreateActionRootElement();
                var interactiveEle = ActionXmlUtility.Instance.CreateInteractiveElement(interActive.Id, "SetTaskStatus");
                var setTaskStastusEle = ActionXmlUtility.Instance.CreateSetActionStatusElement(taskStatus.Value);
                var infoEle = ActionXmlUtility.Instance.CreateInfoElement(CurrentCase.Id, CurrentTask.Id);
                rootElement = ActionXmlUtility.Instance.GeneratorActionXml(rootElement, interactiveEle,
                                                                           infoEle, setTaskStastusEle);
                if (!Connector.SendAction(rootElement, PresetValues.MonitorIp, PresetValues.MonitorPort))
                {
                    return CamelCaseJson(new AjaxResult(false, Resources.MessageResource.SendActionError));
                }
                ApplicationContainer.Add(PresetValues.InteractiveKeys.SetTaskStatus, interActive.Id);
                ApplicationContainer.Add(PresetValues.ApplicationKeys.TaskStatus, taskStatus.Value);
                ApplicationContainer.Add(PresetValues.ApplicationKeys.SetTaskStatusTime, DateTime.Now);
                return CamelCaseJson(AjaxResult.TrueResult);
            }
            return CamelCaseJson(new AjaxResult(false, Resources.MessageResource.Save_Error));
        }

        /// <summary>
        /// 检查后台是否已经完成设置任务状态
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult CheckInteractive()
        {
            var interactiveId = ApplicationContainer.Read<long?>(PresetValues.InteractiveKeys.SetTaskStatus);
            var taskStatus =
                ApplicationContainer.Read<TaskStatusType?>(PresetValues.ApplicationKeys.TaskStatus);
            var setTaskStatusTime =
                ApplicationContainer.Read<DateTime>(PresetValues.ApplicationKeys.SetTaskStatusTime);
            if (interactiveId.HasValue && taskStatus.HasValue && setTaskStatusTime != default(DateTime))
            {
                var interactive = DataProvider.InteractiveService.GetModelById(interactiveId.Value);
                if (interactive != null)
                {
                    if (interactive.InteractiveStatus == InteractiveStatus.End)
                    {
                        CurrentTask.TaskStatus = taskStatus.Value;
                        var serviceResult = DataProvider.TaskService.UpdateOnly(CurrentTask, p => p.TaskStatus, p => p.Id == CurrentTask.Id);
                        if (!serviceResult.ExecutedSuccess)
                            return CamelCaseJson(new AjaxResult(false, serviceResult.Message));
                        CacheContainer.Remove(PresetValues.ApplicationKeys.CurrentTask);
                    }
                    bool isTimeout = false;
                    if ((DateTime.Now - setTaskStatusTime).TotalSeconds >= PresetValues.Timeouts.SetTaskStatus)
                    {
                        SaveInteractiveTimeout(interactive);
                        isTimeout = true;
                    }
                    if (interactive.InteractiveStatus != InteractiveStatus.Starting)
                    {
                        ApplicationContainer.Remove(PresetValues.InteractiveKeys.SetTaskStatus);
                        ApplicationContainer.Remove(PresetValues.ApplicationKeys.TaskStatus);
                        ApplicationContainer.Remove(PresetValues.ApplicationKeys.SetTaskStatusTime);
                    }
                    return isTimeout
                               ? CamelCaseJson(new AjaxResult(false, "超时，该操作未完成"))
                               : CamelCaseJson(new AjaxResult(true) { Expandos = new { interactive.InteractiveStatus } });
                }
            }
            return CamelCaseJson(new AjaxResult(false, string.Format("当前线程中无{0}的值", PresetValues.InteractiveKeys.SetTaskStatus)));
        }

        [HttpPost]
        public ActionResult AutoSearch(long maxRecordId, string type = "dataRecord",
                                       string localNum = null, string remoteNum = null,
                                       string groupNum = null)
        {
            if (type == "dataRecord")
            {
                LoadDataRecordListViewData();
                var drFilter =
                    DataContainer.Read<DataRecordFilter>(PresetValues.SessionKeys.SearchFilter);
                var dataRecords =
                    DataProvider.DataRecordService.GetDataRecords(CurrentTask.Id, maxRecordId,
                                                                  drFilter);
                ReGenerateTitle(dataRecords);
                return PartialView("_DataRecords", dataRecords);
            }
            if (type == "dataIMRecord")
            {
                var dataIMRecords =
                    DataProvider.DataIMRecordService.GetDataIMRecords(CurrentTask.Id, maxRecordId,
                                                                      localNum, remoteNum, groupNum);
                return PartialView("_DataIMRecords", dataIMRecords);
            }
            return new EmptyResult();
        }

        [HttpPost]
        public ActionResult DeleteRecords(long[] dataRecordIds)
        {
            var serviceResult = DataProvider.DataRecordService.DeleteByIds(dataRecordIds);
            if (serviceResult.ExecutedSuccess)
            {
                if (serviceResult.ReturnObj != null)
                {
                    foreach (string filePath in serviceResult.ReturnObj)
                    {
                        DeleteFile(filePath);
                    }
                }
            }
            return
                CamelCaseJson(new AjaxResult(serviceResult.ExecutedSuccess, serviceResult.Message));
        }

        public ActionResult HistoryDataRecordList(DataRecordListModel drlModel)
        {
            LoadDataRecordListViewData();
            if (string.IsNullOrWhiteSpace(drlModel.OrderField))
                drlModel.OrderField = "Id";
            var drFilter = new DataRecordFilter { TaskId = drlModel.TaskId };
            drFilter.MergeFrom(drlModel);
            DataContainer.Add(PresetValues.SessionKeys.SearchFilter, drFilter);
            SetDataRecordList(drlModel);
            return View(drlModel);
        }

        public ActionResult ExportRecords(long[] drIds, bool? isIncludeFile)
        {
            var dataRecords = DataProvider.DataRecordService.GetDataRecords(drIds);
            ReGenerateTitle(dataRecords);
            var supportFields = SupportUtility.GetDisplayField();
            var fieldsInDb =
                DataProvider.DisplayFieldService.GetAllModels().Select(p => p.FieldName).ToList();
            IList<SupportField> displayFields = !fieldsInDb.Any()
                                      ? supportFields
                                      : supportFields.Where(p => fieldsInDb.Contains(p.PropertyName)).ToList();
            //导出的csv文件需要包含导出显示的字段，如FilePath
            displayFields = displayFields.Concat(SupportUtility.GetExportField()).ToList();
            using (var memoryStream = new MemoryStream())
            {
                string downloadName = string.Format("{0:yyyy-MM-dd}.csv", DateTime.Now);
                using (var sw = new StreamWriter(memoryStream, Encoding.UTF8))
                {
                    SerializeCsv(dataRecords, displayFields.ToDictionary(p => p.PropertyName, p => p.DisplayText), sw);
                }
                var filePaths =
                        dataRecords.Where(p => !string.IsNullOrWhiteSpace(p.FilePath))
                                   .Select(p => p.FilePath)
                                   .ToArray();
                if (isIncludeFile.HasValue && isIncludeFile.Value && filePaths.Any())
                {
                    downloadName = string.Format("NetSurveillance.{0:yyyy-MM-dd}.zip", DateTime.Now);
                    var outPutBytes = ZipUtility.Compress(downloadName, memoryStream.ToArray(), filePaths);
                    return File(outPutBytes, "application/zip", downloadName);
                }
                return File(memoryStream.ToArray(), System.Net.Mime.MediaTypeNames.Application.Octet, downloadName);
            }
        }

        public ActionResult DataIMRecordList(DataIMRecordListModel dataIMRecordList)
        {
            if (!dataIMRecordList.TaskId.HasValue || dataIMRecordList.TaskId.Value <= 0)
                dataIMRecordList.TaskId = CurrentTask != null ? CurrentTask.Id : -1;
            var dimrFilter = new DataIMRecordFilter {IsTakeAll = dataIMRecordList.DisplayAll};
            dimrFilter.MergeFrom(dataIMRecordList);
            int pageSize = PageSize,
                pageIndex = dataIMRecordList.PageIndex;
            if (dataIMRecordList.DataIMRecordId.HasValue && (!dataIMRecordList.IsNeedCalcPageIndex.HasValue
                                                             || dataIMRecordList.IsNeedCalcPageIndex.Value))
            {
                pageIndex =
                    DataProvider.DataIMRecordService.CaclPageIndex(dataIMRecordList.DataIMRecordId.Value, pageSize);
                dataIMRecordList.IsNeedCalcPageIndex = false;
            }
            int? totalCount;
            var dataIMRecords =
                DataProvider.DataIMRecordService.GetDataIMRecords(pageIndex,
                                                                  pageSize, dimrFilter, out totalCount);
            dataIMRecordList.DataIMRecords = dataIMRecords;
            if (CurrentTask != null)
                dataIMRecordList.TaskStatus = CurrentTask.TaskStatus;
            int currCount = pageIndex <= 1 ? pageSize : pageIndex * pageSize;
            string currCountDesc = string.Format("{0}-{1}", (pageIndex <= 1 ? 1 : (pageIndex - 1) * pageSize),
                                                 (totalCount > currCount) ? currCount : totalCount);
            if (dataIMRecordList.DisplayAll)
                currCountDesc = string.Format("1-{0}", totalCount);
            dataIMRecordList.TotalCount = totalCount.HasValue ? totalCount.Value : 0;
            dataIMRecordList.CurrentCount = currCountDesc;
            dataIMRecordList.IsLastPage = currCount >= totalCount;

            ViewBag.IsHideDelete = CurrentUser == null || CurrentUser.UserPermission == null ||
                                   (CurrentUser.UserPermission.Permission & PermissionType.Delete) ==
                                   0;

            return View(dataIMRecordList);
        }

        public ActionResult DownloadFile(long drId)
        {
            var dr = DataProvider.DataRecordService.GetModelById(drId);
            if (dr == null || string.IsNullOrWhiteSpace(dr.FilePath))
                return Content("该记录没有找到匹配的文件");
            string fileName = Path.GetFileName(dr.FilePath);
            return File(dr.FilePath, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
        }

        public ActionResult ShowDataRecordContent(long drId)
        {
            var dr = DataProvider.DataRecordService.GetModelById(drId);
            if (dr == null || string.IsNullOrWhiteSpace(dr.Content))
                return Content("该记录无详细内容或没有找到该记录");
            return Content(dr.Content);
        }

        public ActionResult ShowDataRecordFile(long drId)
        {
            var dr = DataProvider.DataRecordService.GetModelById(drId);
            if (dr == null || string.IsNullOrWhiteSpace(dr.FilePath)
                || !System.IO.File.Exists(dr.FilePath))
                return Content("该记录无详细内容或没有找到该记录");
            return Content(System.IO.File.ReadAllText(dr.FilePath));
        }

        public ActionResult IMFiles(string localNum, string groupNum)
        {
            var datarecords = DataProvider.DataIMRecordService.GetQQFileResults(localNum, groupNum);
            ReGenerateTitle(datarecords);
            return PartialView("_IMFiles", datarecords);
        }

        /// <summary>
        /// 序列化数据集为csv
        /// </summary>
        /// <param name="drResults">DataRecordResult列表</param>
        /// <param name="displayFields">需要显示的字段</param>
        /// <param name="sw"></param>
        protected void SerializeCsv(IEnumerable<DataRecordResult> drResults,
                                    Dictionary<string, string> displayFields, StreamWriter sw)
        {
            CsvConfig<DataRecordResult>.CustomHeadersMap = displayFields;
            CsvSerializer.SerializeToWriter(drResults, sw);
        }

        private void LoadDataRecordListViewData()
        {
            ViewBag.SupportFields = SupportUtility.GetDisplayField();
            ViewBag.DisplayFields =
                DataProvider.DisplayFieldService.GetAllModels().Select(p => p.FieldName).ToList();
            ViewBag.IsHideDelete = CurrentUser == null || CurrentUser.UserPermission == null ||
                                   (CurrentUser.UserPermission.Permission & PermissionType.Delete) ==
                                   0;
        }

        private void SetDataRecordList(DataRecordListModel drlModel)
        {
            int? totalCount;
            int pageSize = PageSize, pageIndex = drlModel.PageIndex;
            var drFilter = new DataRecordFilter
                {
                    IsTakeAll = drlModel.DisplayAll,
                    TaskId = drlModel.TaskId
                };
            drFilter.MergeFrom(drlModel);
            drFilter.IsTakeNoTitle = IsShowNoTitleRecord;
            var dataRecordResults =
                DataProvider.DataRecordService.GetDataRecords(pageIndex, pageSize, drFilter, out totalCount);
            int currCount = pageIndex <= 1 ? pageSize : pageIndex * pageSize;
            string currCountDesc = string.Format("{0}-{1}", (pageIndex <= 1 ? 1 : (pageIndex - 1) * pageSize),
                                                 (totalCount > currCount) ? currCount : totalCount);
            if (drlModel.DisplayAll)
                currCountDesc = string.Format("1-{0}", totalCount);
            drlModel.DataRecords = dataRecordResults;
            drlModel.TotalCount = totalCount.HasValue ? totalCount.Value : 0;
            drlModel.CurrentCount = currCountDesc;
            drlModel.IsLastPage = currCount >= totalCount;
            if (CurrentTask != null)
                drlModel.TaskStatus = CurrentTask.TaskStatus;

            ReGenerateTitle(drlModel);
        }

        private void ReGenerateTitle(DataRecordListModel dataRecordListModel)
        {
            if (dataRecordListModel == null || dataRecordListModel.DataRecords == null ||
                dataRecordListModel.DataRecords.Count == 0) return;
            foreach (var dataRecord in dataRecordListModel.DataRecords.Where(p => string.IsNullOrWhiteSpace(p.Title) &&
                        !string.IsNullOrWhiteSpace(p.ActionCode)))
            {
                var dataRecordActions =
                    DataProvider.DataRecordService.GetDataRecordActions(dataRecord.Id).OrderBy(p => p.SortOrder);
                dataRecord.Title = XmlResource.Format(dataRecord.ActionCode, dataRecordActions.Select(p => p.ActionDesc).ToArray());
            }
        }

        private void ReGenerateTitle(IEnumerable<DataRecord> drResults)
        {
            if (drResults == null || !drResults.Any()) return;
            var needGenerateResults =
                drResults.Where(p => string.IsNullOrWhiteSpace(p.Title) && !string.IsNullOrWhiteSpace(p.ActionCode))
                         .ToList();
            var needIds = needGenerateResults.Select(p => p.Id).ToArray();
            if (!needIds.Any()) return;
            var allDrActions = DataProvider.DataRecordService.GetDataRecordActions(needIds);
            foreach (var drResult in needGenerateResults)
            {
                long drId = drResult.Id;
                var drActionDescs =
                    allDrActions.Where(p => p.DataRecordId == drId)
                                .OrderBy(p => p.SortOrder)
                                .Select(p => p.ActionDesc)
                                .ToArray();
                drResult.Title = XmlResource.Format(drResult.ActionCode, drActionDescs);
            }
        }

        private void DeleteFile(string filePath)
        {
            if (string.IsNullOrWhiteSpace(filePath) || !System.IO.File.Exists(filePath))
                return;
            System.IO.File.Delete(filePath);
        }

        #region 生成ztree数据
        /// <summary>
        /// 生成当前任务ztree数据
        /// </summary>
        /// <returns>当前任务ztree数据</returns>
        private IList<ZTreeNode> GeneratorTreeData(long taskId)
        {
            var ztreeNodes = new List<ZTreeNode>
                {
                    GenerateHostNode(taskId),
                    GenerateProtocolNode(taskId)
                };
            var keywordRootNode = new ZTreeNode
                {
                    Id = taskId + 3,
                    Name = "关键字",
                    IsParent = true,
                    ParentId = 0,
                    Children = GeneratorKeywordNodes(taskId),
                    Click = GeneratorClickString(Url.Action("DataRecordList", new { keywordId = -1 }))
                };
            ztreeNodes.Add(keywordRootNode);
            ztreeNodes.Add(GenerateAcctNode(taskId));

            return ztreeNodes;
        }

        private ZTreeNode GenerateHostNode(long taskId, string drViewName = "DataRecordList")
        {
            var hosts =
                DataProvider.HostService.GetAllModels(false, p => p.TaskId == taskId).OrderBy(p => p.Id);
            var groupsByMac = DataProvider.DataRecordService.GroupByMac(taskId);
            var hostRootNode = new ZTreeNode
            {
                Id = taskId + 1,
                Name = "主机",
                IsParent = true,
                ParentId = 0,
                Children = GeneratorHostNodes(hosts, groupsByMac, taskId, drViewName),
                Click = GeneratorClickString(Url.Action(drViewName))
            };
            return hostRootNode;
        }

        private ZTreeNode GenerateProtocolNode(long taskId, string drViewName = "DataRecordList")
        {
            var protocolNode =
                new ZTreeNode
                    {
                        Id = taskId + 2,
                        ParentId = 0,
                        IsParent = true,
                        Name = "协议",
                        Children = new List<ZTreeNode>()
                    };
            protocolNode.Children.Add(GenerateIMNode(taskId, "DataIMRecordList"));
            protocolNode.Children.Add(GenerateEmailNode(taskId, drViewName));
            var sptPrtcs = SupportUtility.GetSupportProtocols();
            var httpPrtc = sptPrtcs.FirstOrDefault(p => p.Name == "http");
            var ftpPrtc = sptPrtcs.FirstOrDefault(p => p.Name == "ftp");
            if (httpPrtc != null)
                protocolNode.Children.Add(GenerateWebPrtcNode(taskId, httpPrtc, drViewName));
            if (ftpPrtc != null)
                protocolNode.Children.Add(GenerateWebPrtcNode(taskId, ftpPrtc, drViewName));
            
            return protocolNode;
        }

        private ZTreeNode GenerateIMNode(long taskId, string drViewName)
        {
            var localQQs = DataProvider.DataIMRecordService.GetLocalIMs(taskId);
            var gorupRecords = DataProvider.DataIMRecordService.GroupRecords(taskId);
            var qqTreeNodes = GenerateQQNodes(localQQs, gorupRecords, taskId, drViewName).ToList();
            var allGroups = DataProvider.DataIMRecordService.GetGroups(taskId);
            qqTreeNodes.AddRange(GenerateGroupNodes(allGroups, taskId, drViewName));
            var imRootNode = new ZTreeNode
                {
                    Name = "即时聊天",
                    IsParent = true,
                    Children = new List<ZTreeNode>
                        {
                            new ZTreeNode
                                {
                                    Name = "QQ",
                                    IsParent = true,
                                    ParentId = 2,
                                    Children = qqTreeNodes
                                }
                        }
                };
            return imRootNode;
        }

        private ZTreeNode GenerateEmailNode(long taskId, string drViewName)
        {
            var emailRootNode = new ZTreeNode
                {
                    Name = "邮件",
                    IsParent = true,
                    Children = new List<ZTreeNode>(),
                    Click = GeneratorClickString(Url.Action(drViewName, new {email = "-1"}))
                };
            var pop3Mails = DataProvider.DataRecordService.GetEmailList(taskId, "pop3");
            var pop3MailNode =
                new ZTreeNode
                    {
                        Name = "收件箱",
                        IsParent = true,
                        Children = GeneratorEmailNodes(pop3Mails, taskId, drViewName),
                        Click =
                            GeneratorClickString(Url.Action(drViewName,
                                                            new {email = "-1", protocol = "pop3"}))
                    };
            emailRootNode.Children.Add(pop3MailNode);
            var smtpMails = DataProvider.DataRecordService.GetEmailList(taskId, "smtp");
            var smtpMailNode =
                new ZTreeNode
                    {
                        Name = "发件箱",
                        IsParent = true,
                        Children = GeneratorEmailNodes(smtpMails, taskId, drViewName),
                        Click =
                            GeneratorClickString(Url.Action(drViewName,
                                                            new {email = "-1", protocol = "smtp"}))
                    };
            emailRootNode.Children.Add(smtpMailNode);
            return emailRootNode;
        }

        private ZTreeNode GenerateWebPrtcNode(long taskId, SupportProtocol sptPrtc, string drViewName = "DataRecordList")
        {
            string protocol = sptPrtc.Name;
            var webPrtcNode =
                new ZTreeNode
                    {
                        Name = sptPrtc.DisplayText,
                        IsParent = true,
                        Click =
                            GeneratorClickString(Url.Action(drViewName,
                                                            new {protocol})),
                        Children = new List<ZTreeNode>()
                    };
            var groupsByMac = DataProvider.DataRecordService.GroupByMac(taskId, protocol);
            var hosts =
                DataProvider.HostService.GetHostsByMacs(groupsByMac.Select(p => p.HostMac).ToArray());
            foreach (var macGroup in groupsByMac)
            {
                string hostMac = macGroup.HostMac;
                var macNode =
                    new ZTreeNode
                        {
                            Name = string.Format("{0} ({1})", hostMac, macGroup.Count),
                            Click =
                                GeneratorClickString(Url.Action(drViewName, new {protocol, hostMac})),
                            Children = new List<ZTreeNode>()
                        };
                foreach (var host in hosts.Where(p => p.Mac == hostMac))
                {
                    var hostNode =
                        new ZTreeNode
                            {
                                Name = host.HostName,
                                Click =
                                    GeneratorClickString(Url.Action(drViewName,
                                                                    new {protocol, hostId = host.Id}))
                            };
                    macNode.Children.Add(hostNode);
                }
                webPrtcNode.Children.Add(macNode);
            }
            return webPrtcNode;
        }

        private ZTreeNode GenerateAcctNode(long taskId, string drViewName = "DataRecordList")
        {
            var acctList = DataProvider.DataRecordService.GetAccountList(taskId);
            var acctRootNode = new ZTreeNode
                {
                    Id = taskId + 4,
                    Name = "敏感信息",
                    IsParent = true,
                    ParentId = 0,
                    Children = GeneratorAccountNodes(acctList, taskId, drViewName),
                    Click = GeneratorClickString(Url.Action(drViewName, new {accountId = -1}))
                };
            return acctRootNode;
        }

        private IList<ZTreeNode> GeneratorHostNodes(IEnumerable<Host> hosts, IList<RecordGroup> groupsByMac,
                                                    long? taskId, string dataRecordViewName)
        {
            var hostTreeNodes = new List<ZTreeNode>();
            var protocols = SupportUtility.GetSupportProtocols();
            foreach (IGrouping<string, Host> hostGroup in hosts.GroupBy(p => p.Mac))
            {
                string hostMac = hostGroup.Key;
                int macGroupCount = 0;
                if (groupsByMac != null && groupsByMac.Any(p => p.HostMac == hostMac))
                {
                    macGroupCount = groupsByMac.First(p => p.HostMac == hostMac).Count;
                }
                string hostGroupName =
                    string.Format("{0} ({1})", hostMac, macGroupCount);
                var hostGroupNode =
                    new ZTreeNode
                        {
                            Name = hostGroupName,
                            Click =
                                GeneratorClickString(Url.Action(dataRecordViewName, new {taskId, hostMac})),
                            Children = new List<ZTreeNode>()
                        };
                foreach (var host in hostGroup)
                {
                    var hostNode = new ZTreeNode
                        {
                            Name = host.HostName,
                            Expandos = new {IsHost = true, HostId = host.Id},
                            Click =
                                GeneratorClickString(Url.Action(dataRecordViewName,
                                                                new {hostId = host.Id, pageIndex = 1, taskId}))
                        };
                    var hostNodeChilds = new List<ZTreeNode>();
                    foreach (var protocol in protocols)
                    {
                        var protocolNode =
                            new ZTreeNode
                                {
                                    Name = protocol.DisplayText,
                                    Click =
                                        GeneratorClickString(Url.Action(dataRecordViewName,
                                                                        new
                                                                            {
                                                                                hostId = host.Id,
                                                                                protocol = protocol.Name,
                                                                                pageIndex = 1,
                                                                                taskId
                                                                            }))
                                };
                        hostNodeChilds.Add(protocolNode);
                    }
                    hostNode.Children = hostNodeChilds;
                    hostGroupNode.Children.Add(hostNode);
                }
                hostTreeNodes.Add(hostGroupNode);
            }
            return hostTreeNodes.Any() ? hostTreeNodes : null;
        }

        private IList<ZTreeNode> GeneratorKeywordNodes(long taskId)
        {
            var treeNodes = new List<ZTreeNode>();
            var keywords = DataProvider.KeywordService.GetAllModels(false, p => p.TaskId == taskId);
            var hitKeywordInfos = DataProvider.KeywordService.GetHitKeywordInfoHosts(taskId);
            foreach (var keyword in keywords)
            {
                long keywordId = keyword.Id;
                string displayKeywordName = string.Format("{0} ({1})",
                                                          keyword.KeywordName,
                                                          hitKeywordInfos.Any(p => p.KeywordId == keywordId)
                                                              ? hitKeywordInfos.Count(p => p.KeywordId == keywordId)
                                                              : 0);
                var keywordNode = new ZTreeNode
                    {
                        Name = displayKeywordName,
                        Click = GeneratorClickString(Url.Action("DataRecordList", new { keywordId, taskId }))
                    };
                if (hitKeywordInfos.Any(p => p.KeywordId == keyword.Id))
                {
                    keywordNode.Children = new List<ZTreeNode>();
                    foreach (var hostGroup in hitKeywordInfos.Where(p => p.KeywordId == keywordId).GroupBy(p => p.Id))
                    {
                        var host = hostGroup.First();
                        string displayHostName = string.Format("{0} ({1})", host.HostName,
                                                               hostGroup.Count());
                        var hostGroupNode = new ZTreeNode
                            {
                                Name = displayHostName,
                                Click = GeneratorClickString(Url.Action("DataRecordList", new { keywordId, hostId = host.Id, taskId }))
                            };
                        keywordNode.Children.Add(hostGroupNode);
                    }
                }
                treeNodes.Add(keywordNode);
            }
            return treeNodes.Any() ? treeNodes : null;
        }

        private IList<ZTreeNode> GeneratorEmailNodes(IEnumerable<string> emailList, long? taskId,
                                                     string dataRecordViewName)
        {
            var treeNodes = new List<ZTreeNode>();

            if (emailList != null)
            {
                treeNodes.AddRange(
                    emailList.Select(emailStr =>
                                     new ZTreeNode
                                         {
                                             Name = emailStr,
                                             Click =
                                                 GeneratorClickString(Url.Action(
                                                     dataRecordViewName,
                                                     new {email = emailStr, taskId}))
                                         }));
            }
            return treeNodes.Any() ? treeNodes : null;
        }

        private IList<ZTreeNode> GeneratorAccountNodes(IEnumerable<SensitiveAccount> accountList, long? taskId,
            string dataRecordViewName)
        {
            var treeNodes = new List<ZTreeNode>();
            var protocols = SupportUtility.GetSupportProtocols();

            if (accountList != null)
            {
                foreach (var sptProtocol in protocols)
                {
                    var protocolActs = accountList.Where(
                        p =>
                        sptProtocol.Name.Equals(p.Protocol,
                                          StringComparison.CurrentCultureIgnoreCase))
                                                  .Select(account =>
                                                          new ZTreeNode
                                                              {
                                                                  Name = account.Account,
                                                                  Click =
                                                                      GeneratorClickString(
                                                                          Url.Action(
                                                                              dataRecordViewName,
                                                                              new
                                                                                  {
                                                                                      accountId = account.Id,
                                                                                      taskId
                                                                                  }))
                                                              }).ToList();
                    var protocolNode =
                        new ZTreeNode
                            {
                                Name = sptProtocol.DisplayText,
                                Children = protocolActs,
                                Click =
                                    GeneratorClickString(Url.Action(dataRecordViewName,
                                                                    new
                                                                        {
                                                                            protocol = sptProtocol.Name,
                                                                            accountId = -1,
                                                                            taskId
                                                                        }))
                            };
                    treeNodes.Add(protocolNode);
                }
            }
            return treeNodes.Any() ? treeNodes : null;
        }

        private IEnumerable<ZTreeNode> GenerateQQNodes(IEnumerable<DataIMRecordResult> localQQs,
                                                 IList<IMRecordGroup> imRecordGroups,
                                                 long? taskId, string dataRecordViewName)
        {
            var qqNodes = new List<ZTreeNode>();
            if (localQQs != null)
            {
                foreach (var localQQ in localQQs)
                {
                    string localNumber = localQQ.LocalNumber;
                    var localQQNode = new ZTreeNode { Name = localQQ.LocalName, Children = new List<ZTreeNode>() };
                    foreach (var localRecordGroup in imRecordGroups.Where(p => p.LocalNumber == localNumber))
                    {
                        string remoteNodeName = string.IsNullOrWhiteSpace(localRecordGroup.RemoteNumber)
                                            ? string.Format("群:{0}", localRecordGroup.GroupName)
                                            : localRecordGroup.RemoteName;
                        string groupNumber = null, remoteNumber = null;
                        if (string.IsNullOrWhiteSpace(localRecordGroup.RemoteNumber))
                            groupNumber = localRecordGroup.GroupNumber;
                        else
                            remoteNumber = localRecordGroup.RemoteNumber;
                        string remoteNameDesc = string.Format("{0} ({1})", remoteNodeName, localRecordGroup.Count);
                        var dynamicParams = new {taskId, localNumber, remoteNumber, groupNumber};
                        var remoteQQNode =
                            new ZTreeNode
                                {
                                    Name = remoteNameDesc,
                                    Click = GeneratorClickString(Url.Action(dataRecordViewName, dynamicParams))
                                };
                        localQQNode.Children.Add(remoteQQNode);
                    }
                    qqNodes.Add(localQQNode);
                }
            }
            return qqNodes;
        }

        private IEnumerable<ZTreeNode> GenerateGroupNodes(IEnumerable<IMRecordGroup> groupList,
                                                          long? taskId, string drViewName)
        {
            var groupNodes = new List<ZTreeNode>();
            if (groupList != null)
            {
                foreach (var recordGroup in groupList)
                {
                    string groupName = string.Format("群:{0} ({1})", recordGroup.GroupName,
                                                     recordGroup.Count),
                           groupNumber = recordGroup.GroupNumber;
                    var groupNode =
                        new ZTreeNode
                            {
                                Name = groupName,
                                Click =
                                    GeneratorClickString(Url.Action(drViewName,
                                                                    new {taskId, groupNumber}))
                            };
                    groupNodes.Add(groupNode);
                }
            }
            return groupNodes;
        }

        private string GeneratorClickString(string url)
        {
            return string.Format("loadFrame(\'{0}\')", url);
        }

        /// <summary>
        /// 生成历史任务ztree数据
        /// </summary>
        /// <returns>历史任务ztree数据</returns>
        private IList<ZTreeNode> GeneratorHistoryTreeData()
        {
            var caseList = DataProvider.CaseService.GetAllModels(false, p => p.CreateUserId == CurrentUser.Id);
            var ztreeNodes = new List<ZTreeNode>
                {
                    new ZTreeNode
                        {
                            Name = "案件",
                            ParentId = 0,
                            Id = 0,
                            IsParent = true,
                            Open = true,
                            Children = GenerateCaseNodes(caseList),
                            Click = GeneratorClickString(Url.Action("HistoryDataRecordList"))
                        }
                };

            return ztreeNodes;
        }

        private IList<ZTreeNode> GenerateCaseNodes(IEnumerable<Case> caseList)
        {
            IList<ZTreeNode> caseNodeList = new List<ZTreeNode>();
            //long currentTaskId = CurrentTask == null ? -1 : CurrentTask.Id;
            foreach (var caseModel in caseList)
            {
                long caseId = caseModel.Id;
                var caseNode = new ZTreeNode
                    {
                        Name = caseModel.Name,
                        IsParent = true,
                        ParentId = 0,
                        Children = new List<ZTreeNode>(),
                        Click = GeneratorClickString(Url.Action("HistoryDataRecordList", new {caseId}))
                    };
                
                var tasks = 
                    DataProvider.TaskService.GetAllModels(false, p => p.CaseId == caseId);
                foreach (var task in tasks)
                {
                    caseNode.Children.Add(GeneratorHistoryTaskNode(task));
                }
                var hitKeywordInfoHosts = DataProvider.KeywordService.GetHitKeywordInfoHostsByCaseId(caseId);
                var keywordRootNode = new ZTreeNode
                    {
                        Name = "关键字",
                        IsParent = true,
                        Children = new List<ZTreeNode>()
                    };
                foreach (var keywordInfoHostsGroup in hitKeywordInfoHosts.GroupBy(p=>p.KeywordName))
                {
                    string keyword = keywordInfoHostsGroup.Key;
                    var keywordNode = new ZTreeNode
                        {
                            Name = string.Format("{0} ({1})", keyword, keywordInfoHostsGroup.Count()),
                            Click = GeneratorClickString(Url.Action("HistoryDataRecordList", new { keyword, caseId })),
                            Children = new List<ZTreeNode>()
                        };

                    foreach (var hostGroup in keywordInfoHostsGroup.GroupBy(p => p.Id))
                    {
                        var kwInfoHost = hostGroup.First();
                        string hostName = kwInfoHost.HostName;
                        long hostId = kwInfoHost.Id;
                        var hostNode = new ZTreeNode
                            {
                                Name = string.Format("{0} ({1})", hostName, hostGroup.Count()),
                                Click =
                                    GeneratorClickString(Url.Action("HistoryDataRecordList",
                                                                    new { hostId, keyword, caseId }))
                            };
                        keywordNode.Children.Add(hostNode);
                    }
                    keywordRootNode.Children.Add(keywordNode);
                }
                caseNode.Children.Add(keywordRootNode);
                caseNodeList.Add(caseNode);
            }
            return caseNodeList;
        }

        /// <summary>
        /// 生成历史数据任务TreeNode
        /// </summary>
        /// <param name="task">任务Model</param>
        /// <returns>任务TreeNode</returns>
        private ZTreeNode GeneratorHistoryTaskNode(Task task)
        {
            long taskId = task.Id;
            const string drViewName = "HistoryDataRecordList";
            var taskNode = new ZTreeNode
                {
                    Name = task.Name,
                    IsParent = true,
                    Children = new List<ZTreeNode>(),
                    Click = GeneratorClickString(Url.Action(drViewName, new {taskId}))
                };
            
            taskNode.Children.Add(GenerateHostNode(taskId, drViewName));
            taskNode.Children.Add(GenerateProtocolNode(taskId, drViewName));
            taskNode.Children.Add(GenerateAcctNode(taskId, drViewName));

            return taskNode;
        }
        #endregion
    }
}
